#pragma once

#include "adalog/LogEvent.h"
#include <memory>
#include <list>

#if __cplusplus >= 201703L
    #include <shared_mutex>
#else
    #include <mutex>
#endif

namespace adalog
{
    /**
     * 自定义输出格式详解：
     * %n: Logger的名称
     * %l: 日志等级
     * %t: 线程ID
     * %v: 日志正文
     * %Y: 年份
     * %m: 月份, 01 ~ 12
     * %d: 日期，01 ~ 31
     * %H: 小时, 00 ~ 12
     * %M: 分钟, 00 ~ 59
     * %S: 秒数, 00 ~ 59
     * %F: 日志记录发生时所在文件的文件名
     * %L: 日志记录发生时所在文件的行号
     *
     * 默认输出格式: "[%Y-%m-%d %H:%M:%S] [%l] [%n] [%t] [%F:%L] %v\n"
     */
    class LogFormatter
    {
    public:
        using Ptr = std::shared_ptr<LogFormatter>;
        class PatternItem;
    public:
        LogFormatter();
        LogFormatter(const std::string& pattern);

        virtual ~LogFormatter();

        virtual std::string Format(LogEvent::Ptr event);
        void SetPattern(const std::string& pattern);
    private:
        std::string pattern_;
        std::list<std::unique_ptr<PatternItem>> pattern_items_;
        // 允许多个线程访问Format()，但只允许一个线程访问SetPattern()
#if __cplusplus >= 201703L
        std::shared_mutex mtx_;
#else
        std::mutex mtx_;
#endif
    };

    class LogFormatter::PatternItem
    {
    public:
        virtual ~PatternItem() = default;
        virtual void Append(std::ostream& os, LogEvent::Ptr event) = 0;
    };

} // namespace adalog